package com.ihg.hiex.entity.user;

import java.beans.Transient;
import java.util.Arrays;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import com.ihg.hiex.entity.session.participator.SessionFacilitator;

/**
 * 账户
 * 
 * @author mohanlan
 */
@Entity
@Table(name = "account")
public class Account {
	
    @Id
    @GeneratedValue
    private Long id;

    /** 邮箱 */
    private String email;

    /** 密码 */
    private String password;

    /** 权限 */
    private String authority;

    /** 手机号 */
    private String mobile;

    /** 是否启用 */
    @Column(name = "is_disabled")
    private boolean disabled;
    
    /**
     * the default constructor.
     */
    public Account() {
    }
    
    /**
     * @param assessor 
     */
    public Account(Assessor assessor) {
        this.authority = Role.ASSESSOR.name();
        this.mobile = assessor.getTelephone();
        this.email = assessor.getEmail().toLowerCase();
    }
    
    /**
     * 
     * @param delegate
     */
    public Account(Delegate delegate) {
        this.authority = Role.DELEGATE.name();
        this.mobile = delegate.getTelephone();
        this.email = delegate.getEmail().toLowerCase();
    }
    
    /**
     * @param administrator
     */
    public Account(Administrator administrator) {
        this.authority = Role.ADMIN.name();
        this.mobile = administrator.getTelephone();
        this.email = administrator.getEmail().toLowerCase();
    }
    
    /**
     * @param facilitator
     */
    public Account(SessionFacilitator facilitator) {
        this.authority = Role.FACILITATOR.name();
        this.email = facilitator.getEmail().toLowerCase();
        this.mobile = facilitator.getMobile();
    }
    
    /**
     * @param email
     * @param authority
     * @param mobile
     */
    public Account(String email, String authority, String mobile) {
        this.email = email.toLowerCase();
        this.authority = authority;
        this.mobile = mobile;
    }

    /**
     * Initialize principal basic fields
     * 
     * @return
     */
    public Account initialize() {
        String defaultPassword = this.generateDefaultPassword();
        this.password = this.encodePassword(defaultPassword);
        return this;
    }

    /**
     * @param password
     * @return
     */
    public boolean validPassword(String password) {
        String inputPassword = this.encodePassword(password);
        return StringUtils.equals(inputPassword, this.password);
    }
    
    /**
     * @param password
     * @return
     */
    public Account editPassword(String password) {
        this.password = this.encodePassword(password);
        return this;
    }
    
    /**
     * Reset password
     * 
     * @return
     */
    public Account resetPassword() {
        String defaultPassword = this.generateDefaultPassword();
        this.password = this.encodePassword(defaultPassword);
        return this;
    }
    
    /**
     * using mobile's last 6 digitals as default password
     * 
     * @return
     */
    private String generateDefaultPassword() {
        return StringUtils.substring(this.mobile, this.mobile.length() - 6);
    }

    /**
     * 
     * @param password
     * @return
     */
    public String encodePassword(String password) {
        String saltPassword = StringUtils.join(password, "{", this.email, "}");
        return DigestUtils.md5Hex(saltPassword);
    }
    
    /**
     * 
     * @param authority
     * @return
     */
    public Account addAuthority(String authority) {
        
        List<String> authorities = Arrays.asList(StringUtils.split(this.authority, ","));
    	
    	if(StringUtils.isEmpty(this.authority)) {
    		this.authority = authority;
    	} else if (!authorities.contains(authority)) {
    	    this.authority = this.authority + "," + authority;
        }
        
        return this;
        
    }
    
    /**
     * 
     * @param authority
     * @return
     */
    public Account removeAuthority(String authority) {
        this.authority = StringUtils.remove(this.authority, authority).replaceAll(",", " ").trim().replaceAll(" ", ",");
        return this;
    }

    /**
     * 
     * @param authority
     * @return
     */
    public boolean hasAuthority(String authority) {
    	if(this.authority.contains(authority)) {
    		return true;
    	} else {
    		return false;
    	}
    }
    
    /**
     * 
     * @param mobile
     * @return
     */
    public Account edit(String mobile) {
	    this.mobile = mobile;
	    this.resetPassword();
        return this;
    }
    
    /**
     * @return
     */
    public Account disable() {
        this.disabled = true;
        return this;
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public String getIdString() {
        return id.toString();
    }
    
    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }

    /**
     * @return
     */
    public String getEmail() {
        return email;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @return the authority
     */
    public String getAuthority() {
        return authority;
    }

    /**
     * @return the mobile
     */
    public String getMobile() {
        return mobile;
    }

    /**
     * @return the disabled
     */
    public boolean isDisabled() {
        return disabled;
    }

    /**
     * @param id
     *            the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @param email
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     * @param password
     *            the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @param authority
     *            the authority to set
     */
    public void setAuthority(String authority) {
        this.authority = authority;
    }

    /**
     * @param mobile
     *            the mobile to set
     */
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    /**
     * @param disabled
     *            the disabled to set
     */
    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }

}